GtkAccelLabel: add manual accel API
authorRyan Lortie <desrt@desrt.ca>
Mon, 10 Sep 2012 18:36:23 +0000 (14:36 -0400)
committerRyan Lortie <desrt@desrt.ca>
Mon, 17 Sep 2012 16:31:22 +0000 (12:31 -0400)
Add an API to GtkAccelLabel for hardcoding the accel key to be displayed
(ie: allowing us to bypass the GtkAccelGroup lookup).

Use that from the GMenuModel-based GtkMenu construction code instead of
passing around the accel group.

This makes accel labels work in bloatpad again.

This patch effectively removes any hope of automatic runtime accel
changes in GMenuModel-based menus without additional application
support but it leaves the door open for this to be supported again in
the future (if we decide that it's important).

https://bugzilla.gnome.org/show_bug.cgi?id=683738

gtk/gtk.symbols
gtk/gtkaccellabel.c
gtk/gtkaccellabel.h
gtk/gtkapplicationwindow.c
gtk/gtkmodelmenu.c
gtk/gtkmodelmenu.h
gtk/gtkmodelmenuitem.c
gtk/gtkmodelmenuitem.h

index 614f52891592a4488d2ad1762af37e0cdefe1b9e..40d3a31b5c79abe2596f8f83f7a565ed4c0b9e86 100644 (file)
@@ -65,6 +65,7 @@ gtk_accel_label_get_accel_width
 gtk_accel_label_get_type
 gtk_accel_label_new
 gtk_accel_label_refetch
+gtk_accel_label_set_accel
 gtk_accel_label_set_accel_closure
 gtk_accel_label_set_accel_widget
 gtk_accel_map_add_entry
index 452f43cd320af3024b54afbd076600c13eb45a1e..d374faa871ee9fe82312b4aa0f8de8b18fc75afb 100644 (file)
@@ -104,6 +104,9 @@ struct _GtkAccelLabelPrivate
   gchar         *accel_string;       /* has set function */
   guint          accel_padding;      /* should be style property? */
   guint16        accel_string_width; /* seems to be private */
+
+  guint           accel_key;         /* manual accel key specification if != 0 */
+  GdkModifierType accel_mods;
 };
 
 static void         gtk_accel_label_set_property (GObject            *object,
@@ -903,19 +906,31 @@ gtk_accel_label_refetch (GtkAccelLabel *accel_label)
                 "gtk-enable-accels", &enable_accels,
                 NULL);
 
-  if (enable_accels && accel_label->priv->accel_closure)
+  if (enable_accels && (accel_label->priv->accel_closure || accel_label->priv->accel_key))
     {
-      GtkAccelKey *key = gtk_accel_group_find (accel_label->priv->accel_group, find_accel, accel_label->priv->accel_closure);
+      guint accel_key = accel_label->priv->accel_key;
+      GdkModifierType accel_mods = accel_label->priv->accel_mods;
+
+      /* If we don't have a hardcoded value, check the accel group */
+      if (!accel_key)
+        {
+          GtkAccelKey *key = gtk_accel_group_find (accel_label->priv->accel_group, find_accel, accel_label->priv->accel_closure);
+
+          if (key && key->accel_flags & GTK_ACCEL_VISIBLE)
+            {
+              accel_key = key->accel_key;
+              accel_mods = key->accel_mods;
+            }
+        }
 
-      if (key && key->accel_flags & GTK_ACCEL_VISIBLE)
+      /* If we found a key using either method, set it */
+      if (accel_key)
        {
          GtkAccelLabelClass *klass;
          gchar *tmp;
 
          klass = GTK_ACCEL_LABEL_GET_CLASS (accel_label);
-         tmp = _gtk_accel_label_class_get_accelerator_label (klass,
-                                                             key->accel_key,
-                                                             key->accel_mods);
+         tmp = _gtk_accel_label_class_get_accelerator_label (klass, accel_key, accel_mods);
          accel_label->priv->accel_string = g_strconcat ("   ", tmp, NULL);
          g_free (tmp);
        }
@@ -930,3 +945,30 @@ gtk_accel_label_refetch (GtkAccelLabel *accel_label)
 
   return FALSE;
 }
+
+/**
+ * gtk_accel_label_set_accel:
+ * @accel_label: a #GtkAccelLabel
+ * @accelerator_key: a keyval, or 0
+ * @accelerator_mods: the modifier mask for the accel
+ *
+ * Manually sets a keyval and modifier mask as the accelerator rendered
+ * by @accel_label.
+ *
+ * If a keyval and modifier are explicitly set then these values are
+ * used regardless of any associated accel closure or widget.
+ *
+ * Providing an @accelerator_key of 0 removes the manual setting.
+ *
+ * Since: 3.6
+ */
+void
+gtk_accel_label_set_accel (GtkAccelLabel   *accel_label,
+                           guint            accelerator_key,
+                           GdkModifierType  accelerator_mods)
+{
+  accel_label->priv->accel_key = accelerator_key;
+  accel_label->priv->accel_mods = accelerator_mods;
+
+  gtk_accel_label_reset (accel_label);
+}
index a1a9e02b95c382f1a99d77c1278125bfb6a0215a..bf247f11cef4dcb6b97a534f4ca4b0af3880d452 100644 (file)
@@ -90,6 +90,10 @@ void    gtk_accel_label_set_accel_widget  (GtkAccelLabel *accel_label,
 void      gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label,
                                              GClosure      *accel_closure);
 gboolean   gtk_accel_label_refetch           (GtkAccelLabel *accel_label);
+GDK_AVAILABLE_IN_3_6
+void       gtk_accel_label_set_accel         (GtkAccelLabel   *accel_label,
+                                              guint            accelerator_key,
+                                              GdkModifierType  accelerator_mods);
 
 /* private */
 gchar *    _gtk_accel_label_class_get_accelerator_label (GtkAccelLabelClass *klass,
index 4c4eadcfdf500022ed41cd2818f2300aab4cdd6c..0632bed5e49d3b2e1ac4227f2ad8b18dfabd55c3 100644 (file)
@@ -256,7 +256,7 @@ gtk_application_window_update_menubar (GtkApplicationWindow *window)
       g_menu_append_section (combined, NULL, G_MENU_MODEL (window->priv->app_menu_section));
       g_menu_append_section (combined, NULL, G_MENU_MODEL (window->priv->menubar_section));
 
-      window->priv->menubar = gtk_model_menu_create_menu_bar (G_MENU_MODEL (combined), window->priv->accels);
+      window->priv->menubar = gtk_model_menu_create_menu_bar (G_MENU_MODEL (combined));
       gtk_widget_set_parent (window->priv->menubar, GTK_WIDGET (window));
       gtk_widget_show_all (window->priv->menubar);
       g_object_unref (combined);
index bb6a711026eddfebb5047e5b41ee222b6808505b..f2174dd89d07ae4a7d813c8d2a4f7ed5bebced12 100644 (file)
@@ -33,7 +33,6 @@
 
 typedef struct {
   GMenuModel        *model;
-  GtkAccelGroup     *accels;
   GtkMenuShell      *shell;
   guint              update_idle;
   GSList            *connected;
@@ -107,7 +106,7 @@ gtk_model_menu_binding_append_item (GtkModelMenuBinding  *binding,
     {
       GtkMenuItem *item;
 
-      item = gtk_model_menu_item_new (model, item_index, action_namespace, binding->accels);
+      item = gtk_model_menu_item_new (model, item_index, action_namespace);
       gtk_menu_shell_append (binding->shell, GTK_WIDGET (item));
       gtk_widget_show (GTK_WIDGET (item));
       binding->n_items++;
@@ -254,7 +253,6 @@ gtk_model_menu_bind (GtkMenuShell *shell,
 
   binding = g_slice_new (GtkModelMenuBinding);
   binding->model = g_object_ref (model);
-  binding->accels = NULL;
   binding->shell = shell;
   binding->update_idle = 0;
   binding->connected = NULL;
@@ -266,30 +264,25 @@ gtk_model_menu_bind (GtkMenuShell *shell,
 
 
 static void
-gtk_model_menu_populate (GtkMenuShell  *shell,
-                         GtkAccelGroup *accels)
+gtk_model_menu_populate (GtkMenuShell *shell)
 {
   GtkModelMenuBinding *binding;
 
   binding = (GtkModelMenuBinding*) g_object_get_data (G_OBJECT (shell), "gtk-model-menu-binding");
 
-  binding->accels = accels;
-
   gtk_model_menu_binding_populate (binding);
 }
 
 GtkWidget *
 gtk_model_menu_create_menu (GMenuModel    *model,
-                            const gchar   *action_namespace,
-                            GtkAccelGroup *accels)
+                            const gchar   *action_namespace)
 {
   GtkWidget *menu;
 
   menu = gtk_menu_new ();
-  gtk_menu_set_accel_group (GTK_MENU (menu), accels);
 
   gtk_model_menu_bind (GTK_MENU_SHELL (menu), model, action_namespace, TRUE);
-  gtk_model_menu_populate (GTK_MENU_SHELL (menu), accels);
+  gtk_model_menu_populate (GTK_MENU_SHELL (menu));
 
   return menu;
 }
@@ -317,21 +310,20 @@ gtk_menu_new_from_model (GMenuModel *model)
 
   menu = gtk_menu_new ();
   gtk_model_menu_bind (GTK_MENU_SHELL (menu), model, NULL, TRUE);
-  gtk_model_menu_populate (GTK_MENU_SHELL (menu), NULL);
+  gtk_model_menu_populate (GTK_MENU_SHELL (menu));
 
   return menu;
 }
 
 GtkWidget *
-gtk_model_menu_create_menu_bar (GMenuModel    *model,
-                                GtkAccelGroup *accels)
+gtk_model_menu_create_menu_bar (GMenuModel *model)
 {
   GtkWidget *menubar;
 
   menubar = gtk_menu_bar_new ();
 
   gtk_model_menu_bind (GTK_MENU_SHELL (menubar), model, NULL, FALSE);
-  gtk_model_menu_populate (GTK_MENU_SHELL (menubar), accels);
+  gtk_model_menu_populate (GTK_MENU_SHELL (menubar));
 
   return menubar;
 }
@@ -360,7 +352,7 @@ gtk_menu_bar_new_from_model (GMenuModel *model)
   menubar = gtk_menu_bar_new ();
 
   gtk_model_menu_bind (GTK_MENU_SHELL (menubar), model, NULL, FALSE);
-  gtk_model_menu_populate (GTK_MENU_SHELL (menubar), NULL);
+  gtk_model_menu_populate (GTK_MENU_SHELL (menubar));
 
   return menubar;
 }
index 1bc27be3ebd0b02092ae53e40abf773ba984e290..a27c7bda4b440e247a018e874c1fad7895db3af9 100644 (file)
 #include <gio/gio.h>
 
 G_GNUC_INTERNAL
-GtkWidget * gtk_model_menu_create_menu_bar (GMenuModel        *model,
-                                            GtkAccelGroup     *accels);
+GtkWidget * gtk_model_menu_create_menu_bar (GMenuModel        *model);
 
 G_GNUC_INTERNAL
 GtkWidget * gtk_model_menu_create_menu     (GMenuModel        *model,
-                                            const gchar       *action_namespace,
-                                            GtkAccelGroup     *accels);
+                                            const gchar       *action_namespace);
 
 #endif /* __GTK_MODEL_MENU_H__ */
index 450cd9a4bf81b66343b5f0e03dd8b8d64011b186..61e10e5a3c706ee5e2e73b9574583c2542317dd0 100644 (file)
@@ -25,6 +25,7 @@
 #include "gtkactionhelper.h"
 #include "gtkmodelmenu.h"
 #include "gtkwidgetprivate.h"
+#include "gtkaccellabel.h"
 
 struct _GtkModelMenuItem
 {
@@ -107,8 +108,7 @@ static void
 gtk_model_menu_item_setup (GtkModelMenuItem  *item,
                            GMenuModel        *model,
                            gint               item_index,
-                           const gchar       *action_namespace,
-                           GtkAccelGroup     *accels)
+                           const gchar       *action_namespace)
 {
   GMenuAttributeIter *iter;
   GMenuModel *submenu;
@@ -125,12 +125,12 @@ gtk_model_menu_item_setup (GtkModelMenuItem  *item,
       if (action_namespace)
         {
           gchar *namespace = g_strjoin (".", action_namespace, section_namespace, NULL);
-          menu = gtk_model_menu_create_menu (submenu, namespace, accels);
+          menu = gtk_model_menu_create_menu (submenu, namespace);
           g_free (namespace);
         }
       else
         {
-          menu = gtk_model_menu_create_menu (submenu, section_namespace, accels);
+          menu = gtk_model_menu_create_menu (submenu, section_namespace);
         }
 
       gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
@@ -145,6 +145,26 @@ gtk_model_menu_item_setup (GtkModelMenuItem  *item,
       if (g_str_equal (key, "label") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
         gtk_menu_item_set_label (GTK_MENU_ITEM (item), g_variant_get_string (value, NULL));
 
+      else if (g_str_equal (key, "accel") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
+        {
+          GdkModifierType modifiers;
+          guint key;
+
+          gtk_accelerator_parse (g_variant_get_string (value, NULL), &key, &modifiers);
+
+          if (key)
+            {
+              GtkAccelLabel *accel_label;
+
+              /* Ensure that the GtkAccelLabel has been created... */
+              (void) gtk_menu_item_get_label (GTK_MENU_ITEM (item));
+              accel_label = GTK_ACCEL_LABEL (gtk_bin_get_child (GTK_BIN (item)));
+              g_assert (accel_label);
+
+              gtk_accel_label_set_accel (accel_label, key, modifiers);
+            }
+        }
+
       else if (g_str_equal (key, "action") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
         gtk_actionable_set_namespaced_action_name (GTK_ACTIONABLE (item), action_namespace,
                                                    g_variant_get_string (value, NULL));
@@ -260,14 +280,13 @@ gtk_model_menu_item_class_init (GtkModelMenuItemClass *class)
 GtkMenuItem *
 gtk_model_menu_item_new (GMenuModel        *model,
                          gint               item_index,
-                         const gchar       *action_namespace,
-                         GtkAccelGroup     *accels)
+                         const gchar       *action_namespace)
 {
   GtkModelMenuItem *item;
 
   item = g_object_new (GTK_TYPE_MODEL_MENU_ITEM, NULL);
 
-  gtk_model_menu_item_setup (item, model, item_index, action_namespace, accels);
+  gtk_model_menu_item_setup (item, model, item_index, action_namespace);
 
   return GTK_MENU_ITEM (item);
 }
index 9e35327f545994ecfbba0ee6d0c7e54acd0c1d9f..655f07341b56d6d22a7e51537808f209c4ef02a9 100644 (file)
@@ -36,7 +36,6 @@ GType                   gtk_model_menu_item_get_type                    (void) G
 G_GNUC_INTERNAL
 GtkMenuItem *           gtk_model_menu_item_new                         (GMenuModel        *model,
                                                                          gint               item_index,
-                                                                         const gchar       *action_namespace,
-                                                                         GtkAccelGroup     *accels);
+                                                                         const gchar       *action_namespace);
 
 #endif /* __GTK_MODEL_MENU_ITEM_H__ */